
/*
 * F_Inicializacion.c
 *
 *  Created on: 04/11/2011
 *      Author: tacho
 */

#include "../../headers/GlobalHeaderPFS.h"
#include "../../headers/Constantes_PFS.h"

extern volatile sig_atomic_t dump;
extern mbr bootSector;
extern uint32_t *fatRegion;
extern char* handlerArchivoMapeado;
extern pthread_mutex_t mutex_array_conexiones;
extern t_conexion * array_conexiones;
extern struct_config configuracion;
extern int32_t cantBloquesXCache;
extern tNodoCache * lCaches;
extern pthread_mutex_t mutex_caches;
extern pthread_mutex_t mutex_fatRegion;
extern t_log *logger;
extern pthread_t thread_msync_id;
extern pthread_t thread_consola;
extern int32_t sali;
extern int32_t cantEntradasDir;
extern int32_t cantEntradasDirMax;
extern pthread_mutex_t mutex_cache_entradasDir;
extern tnodoCacheEntradasDir * cacheEntradasDir;
extern tDirectoryEntry entradaDelDirectorioActual;


/*-------------------------------------------------------------------------*/
/**
Castea el primer bloque a la estructura del BootSector.
 */
void leerBootSector(){

	tBloque contenidoBloque;
	pedirLecturaDeBloque(0, &contenidoBloque);
	memcpy(&bootSector,contenidoBloque.bufferBloque,sizeof(mbr));


}

/*-------------------------------------------------------------------------*/
/**

 */
void leerYcachearFatRegion(){
	//printf("%i",bootSector.sectoresPorFat);
	fatRegion = NULL;


	fatRegion = (uint32_t*) malloc((bootSector.sectoresPorFat*TAMANO_SECTOR));
	//fatRegion = calloc(1000,sizeof(int32_t));

	//(bootSector.sectoresTotales/bootSector.sectoresPorCluster)*TAMANO_ENTRADA_FAT);
	uint32_t bloqueInicioDeFat= (uint32_t) bootSector.sectoresReservados / SECTORESXBLOQUE;
	uint32_t cantBloquesDeLaFat= bootSector.sectoresPorFat/ SECTORESXBLOQUE;
	uint32_t entradasXBloque = TAMANO_BLOQUE/TAMANO_ENTRADA_FAT;
	uint32_t var;
	//puts("2");
	tBloque bloque;
	for (var = 0; var < cantBloquesDeLaFat; var++) {
		pedirLecturaDeBloque(bloqueInicioDeFat+var,&bloque);
		memcpy(fatRegion + entradasXBloque*var,&bloque,sizeof(tBloque));
	}

}

/*-------------------------------------------------------------------------*/
/**

 */
void inicializarConexiones(){

int32_t addrlen = sizeof(struct sockaddr_in);
	int32_t i,comparacion_string, raid_activo = 0;
	nipc paquete_mando, paquete_recibo;
	//INICIO MUTEX ARRAY DE CONEXIONES
	pthread_mutex_init (&mutex_array_conexiones, NULL);

	//Direccion local pfs
	struct sockaddr_in *direccion_local = malloc(addrlen);
	//Direccion remota(a la que me quiero conectar)
	struct sockaddr_in *direccion_remota = malloc(addrlen);


	direccion_remota->sin_family = AF_INET;

	direccion_remota->sin_addr.s_addr = inet_addr(configuracion.IP);
	direccion_remota->sin_port = htons(configuracion.Puerto);

	t_conexion * arrayConexiones = NULL;
	for(i=0;i<configuracion.cantMaxConexiones;i++){
		//array_conexiones[i].descriptor = socket(AF_INET,SOCK_STREAM,0);
		if(i==0){
			arrayConexiones = (t_conexion *) malloc (sizeof(t_conexion));
			array_conexiones = arrayConexiones;
		}else{
			arrayConexiones->sgte = (t_conexion *) malloc (sizeof(t_conexion));
			arrayConexiones = arrayConexiones->sgte;
		}
		arrayConexiones->sgte=0;
		arrayConexiones->descriptor = socket(AF_INET,SOCK_STREAM,0);
		direccion_local->sin_family = AF_INET;
		direccion_local->sin_addr.s_addr = INADDR_ANY;
		direccion_local->sin_port = htons(5315+i);
		//bind(arrayConexiones[i].descriptor,(struct sockaddr *)direccion_local, addrlen);
		connect(arrayConexiones->descriptor,(struct sockaddr *)direccion_remota,addrlen);
		arrayConexiones->enUso = 0;

	}
	i = 0;
	arrayConexiones = array_conexiones;
	for(i=0;i<configuracion.cantMaxConexiones;i++){
		while(raid_activo == 0){

			paquete_mando.type = 0;
			paquete_mando.payloadlength = 0;

			if((send(arrayConexiones->descriptor,&paquete_mando,sizeof(nipc),0)) <= 0){
				perror("send");
			}
			if((recv(arrayConexiones->descriptor,&paquete_recibo,sizeof(nipc),0)) <= 0) {
				perror("recv \n");
				exit (1);
			}

			comparacion_string = strcmp(paquete_recibo.payload.info, "RAID NO ACTIVO");
			if(comparacion_string == 0){
				raid_activo = 0;
			}
			else raid_activo = 1;
		}
		arrayConexiones->pfs_id = paquete_recibo.payload.conexion_pfs_id;
		arrayConexiones = arrayConexiones->sgte;
		raid_activo = 0;
	}
}

/*-------------------------------------------------------------------------*/
/**

 */
void inicializar(){

	sali =0;
	configuracion = cargaConfiguracionInicial();
	if(configuracion.logsActivados)
	logger = log_create("Runner",configuracion.PathArchivoLogs, DEBUG | INFO | WARNING, M_CONSOLE_DISABLE);

	if(configuracion.cantMaxConexiones==0){
		handlerArchivoMapeado = ppd_abrirArchivo();

		pthread_create(&thread_msync_id,NULL,(void*)&thread_msync,NULL);
	}else{
		inicializarConexiones();
	}

	cantEntradasDir=0;
	cacheEntradasDir=NULL;

	cantEntradasDirMax=configuracion.tamanoCacheEntradasDir/(sizeof(tDirectoryEntries));
	pthread_mutex_init(&mutex_cache_entradasDir,NULL);
	leerBootSector();
	leerYcachearFatRegion();
	entradaDeRootDirectory(&entradaDelDirectorioActual);

	cantBloquesXCache= ceil(configuracion.tamanoCache/TAMANO_BLOQUE);

	if(configuracion.tamanoCache>0){
	pthread_mutex_init (&mutex_caches, NULL);
	pthread_mutex_init (&mutex_fatRegion, NULL);
	lCaches = NULL;
	signal(SIGUSR1,crearArchCache);
	}

}

/*-------------------------------------------------------------------------*/
/**

 */
void vaciarConexiones(){
	t_conexion * p;
	while(array_conexiones!=NULL){
		p = array_conexiones;
		array_conexiones = array_conexiones->sgte;
		close(p->descriptor);
		pthread_mutex_destroy(&(p->enUso));
		free(p);
	}
}

/*-------------------------------------------------------------------------*/
/**

 */
void finalizar(){
	if(configuracion.cantMaxConexiones==0)pthread_cancel(thread_msync_id);
	pthread_cancel(thread_consola);
	sali=1;
	free(fatRegion);
	if(cantEntradasDir>0){
		while(cacheEntradasDir!=NULL){
			borrarUnaEntradaDirCache();
		}
	}
	vaciarConexiones();
	if(configuracion.logsActivados)
	log_destroy(logger);

	//delete(&configuracion);
}
